#include "serverdialog.h"
#include "ui_serverdialog.h"

ServerDialog::ServerDialog(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::ServerDialog)
{
    ui->setupUi(this);
    // 信号和槽连接
    connect(ui->portEdit, SIGNAL(textChanged(QString)), this, SLOT(enableCreateBtn()));
    connect(&timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
    // 客户端发送连接请求时会发送newConnection()信号
    connect(&tcpServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
}

ServerDialog::~ServerDialog()
{
    delete ui;
}

void ServerDialog::enableCreateBtn()
{
    bool ok;
    ui->portEdit->text().toUShort(&ok);
    ui->createButton->setEnabled(ok);
}

// 创建服务器按钮的槽函数
void ServerDialog::on_createButton_clicked()
{
    port = ui->portEdit->text().toShort();
    // 设置IP和Port
    if(tcpServer.listen(QHostAddress::Any, port) == true)
    {
        qDebug() << "创建服务器成功!";
        // 禁用按钮和port输入
        ui->createButton->setEnabled(false);
        ui->portEdit->setEnabled(false);
        // 启动定时器
        timer.start(3000);  // 每隔3秒触发一次
    }
    else
    {
        qDebug() << "创建服务器失败!";
    }
}

void ServerDialog::onNewConnection()
{
    // 获取客户端通信的socket
    QTcpSocket *tcpClient = tcpServer.nextPendingConnection();
    // 保存客户端套接字到容器中
    tcpClientList.append(tcpClient);
    // 客户端向服务器发送消息时会发送信号：readyRead()
    connect(tcpClient, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
}

void ServerDialog::onReadyRead()
{
    // 遍历所有在线的客户端socket，看谁给服务器发送了消息
    for(int i = 0; i < tcpClientList.size(); i++)
    {
        // bytesAvailable:获取当前客户端套接字等待读取的字节数
        // 返回0表示没有消息
        // 返回>0表示当前套接字有消息到来
        if(tcpClientList.at(i)->bytesAvailable())
        {
            // 读取
            QByteArray buf = tcpClientList.at(i)->readAll();

            // 先显示出来
            ui->listWidget->addItem(buf);
            ui->listWidget->scrollToBottom();    // 滑至最底部

            // 转发
            sendMessage(buf);
        }
    }
}

void ServerDialog::sendMessage(const QByteArray &buf)
{
    for(int i = 0; i < tcpClientList.size(); i++)
    {
        tcpClientList.at(i)->write(buf);
    }
}

void ServerDialog::onTimeout()
{
    for(int i = 0; i < tcpClientList.size(); i++)
    {
        if(tcpClientList.at(i)->state() == QAbstractSocket::UnconnectedState)
        {
            tcpClientList.removeAt(i);
            i--;    // 类似于迭代器失效，删除后，后面的元素会往前挪动，避免漏判
        }
    }
}

